package com.z996.reflect;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 简述:<br>
 * 了解反射机制
 *
 * @Author zfh18
 * @Date 2024-03-01 18:28
 * @Version 1.0
 **/
public class TestCar {
    /**
     * 获取Class对象多种方式
     */
    @Test
    public void test01() throws NoSuchMethodException, ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 类名 . class
        Class<Car> carClass = Car.class;

        // 对象 . getClass()
        Class<? extends Car> carClass2 = new Car("周飞宏", 52, "红色").getClass();

        //  Class.forName("类全路径")
        Class<?> carClass3 = Class.forName("com.z996.reflect.Car");

        //实例化
        Car car = (Car) carClass3.getConstructor(String.class, int.class, String.class).newInstance("周飞宏", 52, "红色");
        System.out.println(car);
    }

    /**
     * 获取构造方法
     */
    @Test
    public void test02() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class clazz = Car.class;

        // getConstructors()获取所有public的构造方法
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor c : constructors) {
            System.out.println("constructors--->方法名称：" + c.getName() + " 参数个数：" + c.getParameterCount());
        }

        //getDeclaredConstructors()获取所有的构造方法public  private
        Constructor[] constructors1 = clazz.getDeclaredConstructors();
        for (Constructor c : constructors1) {
            System.out.println("constructors1--->方法名称：" + c.getName() + " 参数个数：" + c.getParameterCount());
        }

        //     构造public   指定有参数构造创建对象
        Constructor c1 = clazz.getConstructor(String.class, int.class, String.class);
        Car car1 = (Car) c1.newInstance("夏利", 10, "红色");
        System.out.println(car1);

        // 构造private
        Constructor c2 = clazz.getDeclaredConstructor();
        c2.setAccessible(true); // 开启权限
        Car car2 = (Car) c2.newInstance();
        System.out.println(car2);

    }

    /**
     * 获取属性
     */
    @Test
    public void test03() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<Car> clazz = Car.class;
        Constructor c1 = clazz.getConstructor(String.class, int.class, String.class);
        Car car1 = (Car) c1.newInstance("夏利", 10, "红色");

        //获取所有public属性
        //Field[] fields = clazz.getFields();

        //获取所有属性（包含私有属性）
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //设置允许访问
            field.setAccessible(true);
            field.set(car1, "五菱宏光");
            break;
        }
        System.out.println(car1);
    }

    /**
     * 获取方法
     */
    @Test
    public void test04() throws InvocationTargetException, IllegalAccessException {
        Car car = new Car("奔驰",10,"黑色");
        Class clazz = car.getClass();
        //1 public方法
        Method[] methods = clazz.getMethods();
        for (Method m1:methods) {
            System.out.println(m1.getName());
            //执行方法 toString
            if(m1.getName().equals("toString")) {
                String invoke = (String)m1.invoke(car);
                System.out.println("toString执行了："+invoke);
            }
        }

        //2 private方法
        Method[] methodsAll = clazz.getDeclaredMethods();
        for (Method m:methodsAll) {
            //执行方法 run
            if(m.getName().equals("run")) {
                m.setAccessible(true);
                m.invoke(car);
            }
        }
    }
}
